package com.kingdee.eas.framework.client.multiDetail;

import com.kingdee.bos.appframework.databinding.DataBinder;
import com.kingdee.bos.ctrl.common.CtrlUIEnv;
import com.kingdee.bos.ctrl.kdf.table.IRow;
import com.kingdee.bos.ctrl.kdf.table.KDTSelectBlock;
import com.kingdee.bos.ctrl.kdf.table.KDTSelectManager;
import com.kingdee.bos.ctrl.kdf.table.KDTable;
import com.kingdee.bos.ctrl.swing.KDContainer;
import com.kingdee.bos.ctrl.swing.KDLayout;
import com.kingdee.bos.ctrl.swing.KDLayout.Constraints;
import com.kingdee.bos.ctrl.swing.KDPanel;
import com.kingdee.bos.ctrl.swing.KDWorkButton;
import com.kingdee.bos.dao.AbstractObjectValue;
import com.kingdee.bos.dao.IObjectCollection;
import com.kingdee.bos.dao.IObjectValue;
import com.kingdee.bos.framework.agent.AgentException;
import com.kingdee.bos.metadata.IMetaDataLoader;
import com.kingdee.bos.metadata.MetaDataLoaderFactory;
import com.kingdee.bos.metadata.entity.EntityObjectInfo;
import com.kingdee.eas.common.client.OprtState;
import com.kingdee.eas.framework.client.CoreUI;
import com.kingdee.eas.framework.client.EditUI;
import com.kingdee.eas.framework.client.UILifeCycleEvent;
import com.kingdee.eas.framework.client.UILifeCycleHander;
import com.kingdee.eas.framework.client.UILifeCycleImp;
import com.kingdee.eas.util.client.EASResource;
import com.kingdee.eas.util.client.MsgBox;
import java.awt.BorderLayout;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import javax.swing.JPanel;
import org.apache.log4j.Logger;

public class DetailPanel extends JPanel {
	private static final long serialVersionUID = -5058182349722236713L;
	private static final Logger logger = Logger.getLogger(DetailPanel.class);
	protected KDWorkButton btnAddnewLine;
	protected KDWorkButton btnInsertLine;
	protected KDWorkButton btnRemoveLines;
	protected KDPanel controlPanel;
	protected KDTable entryTable;
	protected KDPanel entryPanel;
	protected KDContainer kdConTitle;
	protected HashMap resourceMap = null;

	protected DataBinder dataBinder = null;

	private AbstractObjectValue newDetailInfo = null;

	private Rectangle rect = null;

	private boolean isAgent = false;

	private CoreUI ui = null;

	private Set addListeners = new HashSet();

	private Set removeListeners = new HashSet();

	private Set insertListeners = new HashSet();

	public DetailPanel(CoreUI ui, DataBinder binder, KDTable kdt,
			AbstractObjectValue newVO, HashMap resourceMap, boolean isAgent)
			throws Exception {
		this(binder, kdt, newVO, resourceMap, isAgent);
		this.ui = ui;
		this.ui.getUILifeCycleHandler().addRuleListener(new UILifeListener());
		actionBackListener backListener = new actionBackListener();
		addAddListener(backListener);
		addInsertListener(backListener);
		addRemoveListener(backListener);
	}

	public DetailPanel(DataBinder binder, KDTable kdt,
			AbstractObjectValue newVO, HashMap resourceMap, boolean isAgent)
			throws Exception {
		CtrlUIEnv.setKingdeeLAF();
		jbInit();
		if (binder == null) {
			logger.debug("databinder is not null!");
			return;
		}
		this.dataBinder = binder;

		this.entryTable = kdt;
		this.rect = this.entryTable.getBounds();
		if (this.entryTable == null) {
			logger.debug("kdtable is not null!");
			return;
		}
		this.newDetailInfo = newVO;
		if (this.newDetailInfo == null) {
			logger.debug("detailinfo is not null!");
		}
		this.resourceMap = resourceMap;
		this.isAgent = isAgent;
		initKDWorkButtion();
		initUIContentLayout();
	}

	private void initStatus(String oprtStatus) {
		if (this.ui != null) {
			boolean enabled = false;
			if (!OprtState.VIEW.equals(oprtStatus)) {
				enabled = true;
			}
			this.btnAddnewLine.setEnabled(enabled);
			this.btnInsertLine.setEnabled(enabled);
			this.btnRemoveLines.setEnabled(enabled);
		}
	}

	private void jbInit() throws Exception {
		this.kdConTitle = new KDContainer();
		this.kdConTitle.setName("kdDetailCon");
		this.kdConTitle.setBounds(0, 5, 100, 24);
		this.kdConTitle.setContainerType(2);
		this.kdConTitle.setTitleStyle(1);
		this.btnAddnewLine = new KDWorkButton();
		this.btnInsertLine = new KDWorkButton();
		this.btnRemoveLines = new KDWorkButton();
		this.controlPanel = new KDPanel();
		this.entryTable = new KDTable();
		this.entryPanel = new KDPanel();
		this.btnAddnewLine.setName("btnAddnewLine");
		this.btnInsertLine.setName("btnInsertLine");
		this.btnRemoveLines.setName("btnRemoveLines");
		this.controlPanel.setName("controlPanel");
		this.entryTable.setName("entryTable");
		this.entryPanel.setName("entryPanel");

		this.btnAddnewLine.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				try {
					DetailPanel.this.actionAddnewLine_actionPerformed(e);
				} catch (Exception e1) {
					e1.printStackTrace();
					DetailPanel.logger.debug("addLine error:" + e);
				}
			}
		});
		this.btnInsertLine.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				try {
					DetailPanel.this.actionInsertLine_actionPerformed(e);
				} catch (Exception e1) {
					e1.printStackTrace();
					DetailPanel.logger.debug("InsertLine error:" + e);
				}
			}
		});
		this.btnRemoveLines.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				try {
					DetailPanel.this.actionRemoveLine_actionPerformed(e);
				} catch (Exception e1) {
					e1.printStackTrace();
					DetailPanel.logger.debug("RemoveLine error:" + e);
				}
			}
		});
		registerBindings();
		registerUIState();
	}

	public KDWorkButton getAddNewLineButton() {
		return this.btnAddnewLine;
	}

	public KDWorkButton getInsertLineButton() {
		return this.btnInsertLine;
	}

	public KDWorkButton getRemoveLinesButton() {
		return this.btnRemoveLines;
	}

	public KDTable getEntryTable() {
		return this.entryTable;
	}

	public void initKDWorkButtion() {
		this.btnAddnewLine
				.setToolTipText(EASResource
						.getString("com.kingdee.eas.framework.FrameWorkResource.Tip_AddLine"));
		this.btnAddnewLine.setIcon(EASResource.getIcon("imgTbtn_addline"));

		this.btnInsertLine
				.setToolTipText(EASResource
						.getString("com.kingdee.eas.framework.FrameWorkResource.Tip_InsertLine"));
		this.btnInsertLine.setIcon(EASResource.getIcon("imgTbtn_insert"));

		this.btnRemoveLines
				.setToolTipText(EASResource
						.getString("com.kingdee.eas.framework.FrameWorkResource.Tip_RemoveLine"));
		this.btnRemoveLines.setIcon(EASResource.getIcon("imgTbtn_deleteline"));
	}

	public void initUIContentLayout() {
		setBounds(this.entryTable.getBounds());
		setLayout(new KDLayout());
		putClientProperty("OriginalBounds", new Rectangle(0, 0,
				this.rect.width, this.rect.height));

		setBounds(this.entryTable.getBounds());
		Rectangle controlRect = new Rectangle(0, 0, this.rect.width, 24);
		this.controlPanel.setBounds(controlRect);
		this.controlPanel.putClientProperty("OriginalBounds", controlRect);
		Rectangle entryRect = new Rectangle(0, 29, this.rect.width,
				this.rect.height - 29);
		this.entryPanel.setBounds(entryRect);
		this.entryPanel.putClientProperty("OriginalBounds", entryRect);

		add(this.controlPanel, new KDLayout.Constraints(13, controlRect));
		add(this.entryPanel, new KDLayout.Constraints(15, entryRect));

		this.controlPanel.setLayout(new KDLayout());
		this.controlPanel.add(this.kdConTitle, new KDLayout.Constraints(0, 5,
				100, 19, 5));

		this.controlPanel.putClientProperty("OriginalBounds", new Rectangle(0,
				0, this.rect.width, 24));

		this.controlPanel.add(this.btnAddnewLine, new KDLayout.Constraints(
				this.rect.width - 86, 5, 22, 19, 9));

		this.controlPanel.add(this.btnInsertLine, new KDLayout.Constraints(
				this.rect.width - 59, 5, 22, 19, 9));

		this.controlPanel.add(this.btnRemoveLines, new KDLayout.Constraints(
				this.rect.width - 32, 5, 22, 19, 9));

		this.entryPanel.setLayout(new BorderLayout(0, 0));
		this.entryTable.setBounds(entryRect);
		this.entryPanel.add(this.entryTable, "Center");
	}

	public void setTitle(String title) {
		if (title == null) {
			title = "sdfdfsdf";
		}
		this.kdConTitle.setTitle(title);
	}

	private void registerBindings() {
	}

	private void registerUIState() {
	}

	public void loadFields() {
	}

	public void storeFields() {
	}

	public void actionAddnewLine_actionPerformed(ActionEvent e)
			throws Exception {
		addLine(this.entryTable);
	}

	public void actionInsertLine_actionPerformed(ActionEvent e)
			throws Exception {
		insertLine(this.entryTable);
	}

	public void actionRemoveLine_actionPerformed(ActionEvent e)
			throws Exception {
		removeLine(this.entryTable);
	}

	protected IObjectValue createNewDetailData(KDTable table) {
		if (table == null) {
			return null;
		}
		if (this.isAgent) {
			EntityObjectInfo entity = MetaDataLoaderFactory
					.getRemoteMetaDataLoader().getEntity(
							this.newDetailInfo.getBOSType());
			try {
				Class agentClz = Class.forName(entity.getBusinessAgent());
				Method method = agentClz.getMethod("copyOvAsNewAgent",
						new Class[] { IObjectValue.class });
				Object obj = method.invoke(agentClz,
						new Object[] { this.newDetailInfo });
				if ((obj instanceof IObjectValue)) {
					return (IObjectValue) obj;
				}
				return null;
			} catch (InvocationTargetException e) {
				e.printStackTrace();
				throw new AgentException(
						"Exception at creating agent instance from BOS value object:"
								+ this.newDetailInfo, e.getCause());
			} catch (Exception e) {
				e.printStackTrace();
				throw new AgentException(
						"Exception at creating agent instance from BOS value object:"
								+ this.newDetailInfo, e);
			}
		}
		return (IObjectValue) this.newDetailInfo.clone();
	}

	private boolean isTableColumnSelected(KDTable table) {
		if (table.getSelectManager().size() > 0) {
			KDTSelectBlock block = table.getSelectManager().get();

			if ((block.getMode() == 4) || (block.getMode() == 8)) {
				return true;
			}
		}

		return false;
	}

	protected void addLine(KDTable table) throws Exception {
		if (table == null) {
			return;
		}
		IObjectValue detailData = createNewDetailData(table);
		fireAddLineBeforeAction(detailData);
		IRow row = table.addRow();
		loadLineFields(table, row, detailData);
		fireAddLineAfterAction(detailData);
	}

	protected void insertLine(KDTable table) throws Exception {
		if (table == null) {
			return;
		}
		IObjectValue detailData = createNewDetailData(table);
		fireInsertLineBeforeAction(detailData);
		IRow row = null;

		if (table.getSelectManager().size() > 0) {
			int top = table.getSelectManager().get().getTop();

			if (isTableColumnSelected(table)) {
				row = table.addRow();
			} else {
				row = table.addRow(top);
			}
		} else {
			row = table.addRow();
		}

		loadLineFields(table, row, detailData);
		fireInsertLineAfterAction(detailData);
	}

	protected void removeLine(KDTable table) throws Exception {
		if (table == null) {
			return;
		}

		if (table.getSelectManager().size() == 0) {
			MsgBox
					.showInfo(
							this,
							EASResource
									.getString("com.kingdee.eas.framework.FrameWorkResource.Msg_NoneEntry"));

			return;
		}

		int top = table.getSelectManager().get().getTop();

		if (table.getRow(top) == null) {
			MsgBox
					.showInfo(
							this,
							EASResource
									.getString("com.kingdee.eas.framework.FrameWorkResource.Msg_NoneEntry"));

			return;
		}

		IObjectValue detailData = (IObjectValue) table.getRow(top)
				.getUserObject();
		fireRemoveLineBeforeAction(detailData);
		table.removeRow(top);
		IObjectCollection collection = (IObjectCollection) table
				.getUserObject();

		if (collection == null) {
			logger.error("collection not be binded to table");
		} else if (detailData != null) {
			collection.removeObject(top);
		}

		fireRemoveLineAfterAction(detailData);
	}

	protected IObjectCollection getBindData(KDTable table) {
		return (IObjectCollection) table.getUserObject();
	}

	protected void loadLineFields(KDTable table, IRow row, IObjectValue obj) {
		this.dataBinder.loadLineFields(table, row, obj);
	}

	protected void storeLineFields(KDTable table, IRow row, IObjectValue obj) {
		this.dataBinder.storeLineFields(table, row, obj);
	}

	public void addAddListener(IDetailPanelListener listener) {
		synchronized (this.addListeners) {
			this.addListeners.add(listener);
		}
	}

	public void addInsertListener(IDetailPanelListener listener) {
		synchronized (this.insertListeners) {
			this.insertListeners.add(listener);
		}
	}

	public void addRemoveListener(IDetailPanelListener listener) {
		synchronized (this.removeListeners) {
			this.removeListeners.add(listener);
		}
	}

	private void fireAddLineBeforeAction(IObjectValue vo) throws Exception {
		Iterator iterator;
		synchronized (this.addListeners) {
			iterator = new HashSet(this.addListeners).iterator();
		}
		DetailPanelEvent event = new DetailPanelEvent(this, vo);
		while (iterator.hasNext()) {
			IDetailPanelListener listener = (IDetailPanelListener) iterator
					.next();
			listener.beforeEvent(event);
		}
	}

	private void fireAddLineAfterAction(IObjectValue vo) throws Exception {
		Iterator iterator;
		synchronized (this.addListeners) {
			iterator = new HashSet(this.addListeners).iterator();
		}
		DetailPanelEvent event = new DetailPanelEvent(this, vo);
		while (iterator.hasNext()) {
			IDetailPanelListener listener = (IDetailPanelListener) iterator
					.next();
			listener.afterEvent(event);
		}
		this.entryTable.repaint();
	}

	private void fireInsertLineBeforeAction(IObjectValue vo) throws Exception {
		Iterator iterator;
		synchronized (this.insertListeners) {
			iterator = new HashSet(this.insertListeners).iterator();
		}
		DetailPanelEvent event = new DetailPanelEvent(this, vo);
		while (iterator.hasNext()) {
			IDetailPanelListener listener = (IDetailPanelListener) iterator
					.next();
			listener.beforeEvent(event);
		}
	}

	private void fireInsertLineAfterAction(IObjectValue vo) throws Exception {
		Iterator iterator;
		synchronized (this.insertListeners) {
			iterator = new HashSet(this.insertListeners).iterator();
		}
		DetailPanelEvent event = new DetailPanelEvent(this, vo);
		while (iterator.hasNext()) {
			IDetailPanelListener listener = (IDetailPanelListener) iterator
					.next();
			listener.afterEvent(event);
		}
		this.entryTable.repaint();
	}

	private void fireRemoveLineBeforeAction(IObjectValue vo) throws Exception {
		Iterator iterator;
		synchronized (this.removeListeners) {
			iterator = new HashSet(this.removeListeners).iterator();
		}
		DetailPanelEvent event = new DetailPanelEvent(this, vo);
		while (iterator.hasNext()) {
			IDetailPanelListener listener = (IDetailPanelListener) iterator
					.next();
			listener.beforeEvent(event);
		}
	}

	private void fireRemoveLineAfterAction(IObjectValue vo) throws Exception {
		Iterator iterator;
		synchronized (this.removeListeners) {
			iterator = new HashSet(this.removeListeners).iterator();
		}
		DetailPanelEvent event = new DetailPanelEvent(this, vo);
		while (iterator.hasNext()) {
			IDetailPanelListener listener = (IDetailPanelListener) iterator
					.next();
			listener.afterEvent(event);
		}
		this.entryTable.repaint();
	}

	class UILifeListener extends UILifeCycleImp {
		UILifeListener() {
		}

		public void beforeOnload(UILifeCycleEvent event) {
			CoreUI ui = (CoreUI) event.getSource();
			DetailPanel.this.initStatus(ui.getOprtState());
		}

		public void onSetDataObject(UILifeCycleEvent event) {
			beforeOnload(event);
		}
	}

	class actionBackListener implements IDetailPanelListener {
		actionBackListener() {
		}

		public void beforeEvent(DetailPanelEvent event) throws Exception {
		}

		public void afterEvent(DetailPanelEvent event) throws Exception {
			if (DetailPanel.this.ui == null)
				return;
			if ((DetailPanel.this.ui instanceof EditUI)) {
				EditUI editUI = (EditUI) DetailPanel.this.ui;
				editUI.refreshFootROw(DetailPanel.this.entryTable);
			}
		}
	}
}